package com.cocotingo.snail.template;

import java.awt.Color;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import com.cocotingo.snail.GraphicsX;
import com.cocotingo.snail.KeyEvent;
import com.cocotingo.snail.MouseEvent;
import com.cocotingo.snail.MouseWheelEvent;
import com.cocotingo.snail.View;

public class SealedView extends View {
	
	private final Hashtable<String, SealedView> nameTable;
	private final List<EventHandler> handlers;
	
	public SealedView() {
		super();
		nameTable = new Hashtable<String, SealedView>();
		handlers = new LinkedList<EventHandler>();
	}
	
	Hashtable<String, SealedView> getNameTable() {
		return this.nameTable;
	}
	
	void setNameTable(Hashtable<String, SealedView> nameTable) {
		this.nameTable.clear();
		this.nameTable.putAll(nameTable);
	}
	
	public SealedView getNamedView(String name) {
		return nameTable.get(name);
	}
	
	//// delegates ////
	
	public static final String PROPERTY_CHANGED_ALPHA = "alphaChanged";
	public static final String PROPERTY_CHANGED_BACKGROUND_COLOR = "backgroundColorChanged";
	public static final String PROPERTY_CHANGED_HIDDEN = "hiddenChanged";
	public static final String PROPERTY_CHANGED_POSITION = "positionChanged";
	public static final String PROPERTY_CHANGED_SIZE = "sizeChanged";
	public static final String GOT_KEYBOARD_FOCUS = "gotKeyboardFocus";
	public static final String LOST_KEYBOARD_FOCUS = "lostKeyboardFocus";
	public static final String MOUSE_ENTERED = "mouseEntered";
	public static final String MOUSE_EXITED = "mouseExited";
	public static final String PRE_KEY_PRESSED = "preKeyPressed";
	public static final String PRE_KEY_RELEASED = "preKeyReleased";
	public static final String PRE_KEY_TYPED = "preKeyTyped";
	public static final String PRE_MOUSE_PRESSED = "preMousePressed";
	public static final String PRE_MOUSE_RELEASED = "preMouseReleased";
	public static final String PRE_MOUSE_CLICKED = "preMouseClicked";
	public static final String PRE_MOUSE_MOVED = "preMouseMoved";
	public static final String PRE_MOUSE_DRAGGED = "preMouseDragged";
	public static final String PRE_MOUSE_WHEEL_MOVED = "preMouseWheelMoved";
	public static final String POST_KEY_PRESSED = "postKeyPressed";
	public static final String POST_KEY_RELEASED = "postKeyReleased";
	public static final String POST_KEY_TYPED = "postKeyTyped";
	public static final String POST_MOUSE_PRESSED = "postMousePressed";
	public static final String POST_MOUSE_RELEASED = "postMouseReleased";
	public static final String POST_MOUSE_CLICKED = "postMouseClicked";
	public static final String POST_MOUSE_MOVED = "postMouseMoved";
	public static final String POST_MOUSE_DRAGGED = "postMouseDragged";
	public static final String POST_MOUSE_WHEEL_MOVED = "postMouseWheelMoved";
	public static final String REPAINT_VIEW = "repaintView";
	public static final String SUBVIEW_ADDED = "subviewAdded";
	public static final String SUBVIEW_REMOVED = "subviewRemoved";
	public static final String SUBVIEW_INDEX_CHANGED = "subviewIndexChanged";
	
	public void addEventHandler(EventHandler listener) {
		handlers.add(listener);
	}
	
	public void removeEventHandler(EventHandler listener) {
		handlers.remove(listener);
	}
	
	public void firePropertyChanged(String property) {
		for (EventHandler listener : handlers) {
			listener.handleViewEvent(this, property, null);
		}
	}
	
	private void fireSimpleEvent(String event) {
		for (EventHandler listener : handlers) {
			listener.handleViewEvent(this, event, null);
		}
	}
	
	private void fireEventWithArgument(String event, Object arg) {
		for (EventHandler listener : handlers) {
			listener.handleViewEvent(this, event, arg);
		}
	}
	
	@Override
	public View setAlpha(float alpha) {
		if (getAlpha() != alpha) {
			super.setAlpha(alpha);
			firePropertyChanged(PROPERTY_CHANGED_ALPHA);
		}
		return this;
	}
	
	@Override
	public View setBackgroundColor(Color backgroundColor) {
		if (getBackgroundColor() != backgroundColor) {
			super.setBackgroundColor(backgroundColor);
			firePropertyChanged(PROPERTY_CHANGED_BACKGROUND_COLOR);
		}
		return this;
	}
	
	@Override
	public View setHidden(boolean hidden) {
		if (isHidden() != hidden) {
			super.setHidden(hidden);
			firePropertyChanged(PROPERTY_CHANGED_HIDDEN);
		}
		return this;
	}
	
	@Override
	public View setPosition(int left, int top) {
		if (getLeft() != left || getTop() != top) {
			super.setPosition(left, top);
			firePropertyChanged(PROPERTY_CHANGED_POSITION);
		}
		return this;
	}
	
	@Override
	public View setSize(int width, int height) {
		if (getWidth() != width || getHeight() != height) {
			super.setSize(width, height);
			firePropertyChanged(PROPERTY_CHANGED_SIZE);
		}
		return this;
	}
	
	@Override
	public void setSubviewIndex(View view, int targetIndex) {
		if (view.getIndex() != targetIndex) {
			super.setSubviewIndex(view, targetIndex);
			fireEventWithArgument(SUBVIEW_INDEX_CHANGED, view);
		}
	}
	
	@Override
	protected void gotKeyboardFocus() {
		fireSimpleEvent(GOT_KEYBOARD_FOCUS);
	}
	
	@Override
	protected void lostKeyboardFocus() {
		fireSimpleEvent(LOST_KEYBOARD_FOCUS);
	}
	
	@Override
	protected void repaintView(GraphicsX g) {
		fireEventWithArgument(REPAINT_VIEW, g);
	}
	
	@Override
	protected void subviewAdded(View subview) {
		super.subviewAdded(subview);
		fireEventWithArgument(SUBVIEW_ADDED, subview);
	}
	
	@Override
	protected void subviewRemoved(View subView) {
		super.subviewRemoved(subView);
		fireEventWithArgument(SUBVIEW_REMOVED, subView);
	}
	
	@Override
	protected void mouseEntered() {
		fireSimpleEvent(MOUSE_ENTERED);
	}
	
	@Override
	protected void mouseExited() {
		fireSimpleEvent(MOUSE_EXITED);
	}
	
	@Override
	protected void preKeyPressed(KeyEvent e) {
		fireEventWithArgument(PRE_KEY_PRESSED, e);
	}
	
	@Override
	protected void preKeyReleased(KeyEvent e) {
		fireEventWithArgument(PRE_KEY_RELEASED, e);
	}
	
	@Override
	protected void preKeyTyped(KeyEvent e) {
		fireEventWithArgument(PRE_KEY_TYPED, e);
	}
	
	@Override
	protected void preMouseClicked(MouseEvent e) {
		fireEventWithArgument(PRE_MOUSE_CLICKED, e);
	}
	
	@Override
	protected void preMouseDragged(MouseEvent e) {
		fireEventWithArgument(PRE_MOUSE_DRAGGED, e);
	}
	
	@Override
	protected void preMouseMoved(MouseEvent e) {
		fireEventWithArgument(PRE_MOUSE_MOVED, e);
	}
	
	@Override
	protected void preMousePressed(MouseEvent e) {
		fireEventWithArgument(PRE_MOUSE_PRESSED, e);
	}
	
	@Override
	protected void preMouseReleased(MouseEvent e) {
		fireEventWithArgument(PRE_MOUSE_RELEASED, e);
	}
	
	@Override
	protected void preMouseWheelMoved(MouseWheelEvent e) {
		fireEventWithArgument(PRE_MOUSE_WHEEL_MOVED, e);
	}
	
	@Override
	protected void postKeyPressed(KeyEvent e) {
		fireEventWithArgument(POST_KEY_PRESSED, e);
	}
	
	@Override
	protected void postKeyReleased(KeyEvent e) {
		fireEventWithArgument(POST_KEY_RELEASED, e);
	}
	
	@Override
	protected void postKeyTyped(KeyEvent e) {
		fireEventWithArgument(POST_KEY_TYPED, e);
	}
	
	@Override
	protected void postMouseClicked(MouseEvent e) {
		fireEventWithArgument(POST_MOUSE_CLICKED, e);
	}
	
	@Override
	protected void postMouseDragged(MouseEvent e) {
		fireEventWithArgument(POST_MOUSE_DRAGGED, e);
	}
	
	@Override
	protected void postMouseMoved(MouseEvent e) {
		fireEventWithArgument(POST_MOUSE_MOVED, e);
	}
	
	@Override
	protected void postMousePressed(MouseEvent e) {
		fireEventWithArgument(POST_MOUSE_PRESSED, e);
	}
	
	@Override
	protected void postMouseReleased(MouseEvent e) {
		fireEventWithArgument(POST_MOUSE_RELEASED, e);
	}
	
	@Override
	protected void postMouseWheelMoved(MouseWheelEvent e) {
		fireEventWithArgument(POST_MOUSE_WHEEL_MOVED, e);
	}

}
